/*
 * © 2010 Autodata Solutions Company. All Rights Reserved
 * This source code is the confidential and proprietary information of Autodata Solutions Company.
 * The user shall not, in whole or in part, copy, publish, disclose or make any use of this source code
 * without the prior written consent of Autodata Solutions Company.
 */
Ext.ns('net.autodata.form.DependentComboBox');

(function () {	
	
	/**
	 * A ComboBox that triggers to load for it's dependents
	 * @class DependentComboBox
	 * @extends Ext.form.ComboBox
	 * @namespace net.autodata.form
	 */
	var ComboBox = Ext.extend(Ext.form.ComboBox, {
		
		/**
		 * @property
		 * @type Array
		 */
        dependents: undefined,
        
        /**
         * @method initComponent
         */
        initComponent: function ()
        {
            ComboBox.superclass.initComponent.apply(this, arguments);

            var store = this.getStore();

            //Create an interceptor to set a default value in the combobox before
            //the listeners to the store's load event are notified
            Ext.util.Observable.capture(store, function (eventName) {
                if (eventName !== 'load') {
                    return true;
                }

                //ASC.log(String.format('{0} ComboBox->store interceptor', this.id));

                //Check to make sure the selected value is still in the store
                var record = store.getById(this.getValue().toString());
                if (!record) {
                    this.setDefaultValue();
                } else {
                    //ASC.log(String.format('{0} ComboBox->store interceptor value found in store', this.id));

                    //The ComoBox sets the value before the store is loaded and therefore displays the
                    //value instead of the display value... we can work around this by setting the text value
                    //when the store is loaded
                    this.setValue(record.get(this.valueField));
                    this.setRawValue(record.get(this.displayField));

                    this.fireEvent('select', this, record, store.indexOf(record));
                }

                return true;

            }, this);

            this.on({
                'change': this.onValueChanged,
                'select': this.onValueSelected,
                scope: this
            });
            
            store.on({
            	'clear': this.clearValue,
            	'requiredparameterexception': this.emptyStore,
            	scope: this
            });

        },
        
        /**
         * @method setDefaultValue
         */
        setDefaultValue: function ()
        {
            //ASC.log(String.format('{0} setDefaultValue', this.id));

            var s = this.getStore(), index = 0;

            if (!this.allowBlank && s.getCount() > 0) {
                var record = s.getAt(index);
                this.setValue(record.id);
            } else {
                this.clearValue();
            }

            this.fireEvent('select', this, record, record ? index : -1);
        },
        
        /**
         * @method setSelectedValue
         * @param {String} value
         */
        setSelectedValue: function (value)
        {
            var record, s = this.getStore(), index = 0;

            s.each(function (r) {
            	if(r.id == value) {
            		record = r;
            	}
            	if(!record)
            		index++;
            });

            this.setValue(record.id);
            this.fireEvent('select', this, record, record ? index : -1);
        },
        
        /**
         * @method onValueChanged
         * @param {HtmlElement} field
         * @param {String} newValue
         * @param {String} oldValue
         * @private
         */
        onValueChanged: function (field, newValue, oldValue)
        {            
            var params = {};
            params[this.valueField] = newValue ? newValue.toString() : undefined;
            this.updateDependents(Ext.applyIf(params, this.getStore().baseParams));
        },
        
        /**
         * @method onValueSelected
         * @param {HtmlElement} field
         * @param {Object} newRecord
         * @param {int} index
         * @private
         */
        onValueSelected: function (field, newRecord, index)
        {
        	var params = {};
        	params[this.valueField] = newRecord ? newRecord.id.toString() : undefined;
            this.updateDependents(Ext.applyIf(params, this.getStore().baseParams));
        },
        
        /**
         * @method compareParams
         * @param {Object} a source list
         * @param {Object} b list to be compared
         */
        compareParams: function (a, b)
        {   
            var match = true;
            Ext.iterate(a, function (paramName, paramValue) {
            	if (paramValue !== b[paramName]) {
            		match = false;
            		return false;
            	}
            }, this);
            
            return match;
        },
        
        /**
         * @method clearValue
         */
        clearValue: function ()
        {
            var original = this.getValue();
            ComboBox.superclass.clearValue.apply(this, arguments);
            if (original !== '') {
                //ASC.log(String.format('{0} clearValue', this.id));
                this.fireEvent('change', this, '', original);
            }
        },

        /**
         * @method updateDependents
         * @param {Object} params
         */
        updateDependents: function (params)
        {
            var a=params;
            Ext.each(this.dependents, function (dependent) {
            	
            	var store = dependent.getStore();
				
				if (!this.compareParams(params, store.baseParams)) {
					dependent.clearValue();
					store.baseParams = params;
					store.load();
				}
            }, this);
        },
        
        /**
         * @method onDestroy
         * @private
         */
        onDestroy: function ()
        {
        	var store = this.getStore(); 
        	if (store) {
            	Ext.util.Observable.release(store);
            	store.un('clear', this.clearValue, this);
            	store.un('requiredparameterexception', this.emptyStore, this);
            }
            ComboBox.superclass.onDestroy.apply(this, arguments);
        },
        
        /**
         * @method emptyStore
         */
        emptyStore: function ()
        {
        	this.getStore().removeAll();
        }
    });	
	
	net.autodata.form.DependentComboBox = ComboBox;	
})();